package com.skyd.andengine;

import java.util.Comparator;

import javax.microedition.khronos.opengles.GL10;

import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.entity.IEntity;
import org.anddev.andengine.entity.modifier.IEntityModifier;
import org.anddev.andengine.entity.modifier.IEntityModifier.IEntityModifierMatcher;
import org.anddev.andengine.entity.shape.IShape;
import org.anddev.andengine.entity.shape.Shape;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.vertex.VertexBuffer;
import org.anddev.andengine.util.Transformation;

import com.skyd.core.common.Direction;
import com.skyd.core.vector.Vector2DF;

/**
 * 以装饰器模式扩展的IShape
 * 
 * @author SkyD
 * 
 */
public class GameShape<T extends IShape> implements IShape {

	/**
	 * 构造函数
	 * 
	 * @param source
	 *            被包装的源对象
	 *            
	 * @param parentActivity 所属GameActivity
	 */
	public GameShape(T source,GameActivity parentActivity) {
		setSource(source);
		// setPositionOffset(new Vector2DF());
		setParentActivity(parentActivity);
	}

	/**
	 * 初始值为null。 功能注释：源对象
	 */
	private T _Source = null;

	/**
	 * 获取Source。 功能注释：源对象
	 * 
	 * @return 当前的IShape类型的值
	 */
	public T getSource() {
		return _Source;
	}

	/**
	 * 设置Source。 功能注释：源对象
	 * 
	 * @param value
	 *            要设置的IShape类型值
	 */
	protected void setSource(T value) {
		_Source = value;
	}

	/**
	 * 设置Source为其默认值(null)。 功能注释：源对象
	 */
	protected void setSourceToDefault() {
		setSource(null);
	}
	
	/**
 * 初始值为null。
 * 功能注释：获取所属GameActivity
 */
	private  GameActivity _ParentActivity = null;
/**
 * 获取ParentActivity。
 * 功能注释：获取所属GameActivity
 * @return 当前的GameActivity类型的值
 */
	public  GameActivity getParentActivity() {
		return _ParentActivity;
	}
/**
 * 设置ParentActivity。
 * 功能注释：获取所属GameActivity
 * @param value 要设置的GameActivity类型值
 */
	public  void setParentActivity(GameActivity value) {
		_ParentActivity = value;
	}	
/**
 * 设置ParentActivity为其默认值(null)。
 * 功能注释：获取所属GameActivity
 */
	public  void setParentActivityToDefault() {
		setParentActivity(null);
	}

	@Override
	public boolean isVisible() {
		return getSource().isVisible();
	}

	@Override
	public void setVisible(boolean pVisible) {
		getSource().setVisible(pVisible);
	}

	@Override
	public boolean isIgnoreUpdate() {
		return getSource().isIgnoreUpdate();
	}

	@Override
	public void setIgnoreUpdate(boolean pIgnoreUpdate) {
		getSource().setIgnoreUpdate(pIgnoreUpdate);
	}

	@Override
	public boolean isChildrenVisible() {
		return getSource().isChildrenVisible();
	}

	@Override
	public void setChildrenVisible(boolean pChildrenVisible) {
		getSource().setChildrenVisible(pChildrenVisible);
	}

	@Override
	public boolean isChildrenIgnoreUpdate() {
		return getSource().isChildrenIgnoreUpdate();
	}

	@Override
	public void setChildrenIgnoreUpdate(boolean pChildrenIgnoreUpdate) {
		getSource().setChildrenIgnoreUpdate(pChildrenIgnoreUpdate);
	}

	@Override
	public int getZIndex() {
		return getSource().getZIndex();
	}

	@Override
	public void setZIndex(int pZIndex) {
		getSource().setZIndex(pZIndex);
	}

	@Override
	public boolean hasParent() {
		return getSource().hasParent();
	}

	@Override
	public IEntity getParent() {
		return getSource().getParent();
	}

	@Override
	public void setParent(IEntity pEntity) {
		getSource().setParent(pEntity);
	}

	@Override
	public float getX() {
		return getSource().getX();
	}

	@Override
	public float getY() {
		return getSource().getY();
	}

	@Override
	public float getInitialX() {
		return getSource().getInitialX();
	}

	@Override
	public float getInitialY() {
		return getSource().getInitialY();
	}

	@Override
	public void setInitialPosition() {
		getSource().setInitialPosition();
	}

	@Override
	public void setPosition(IEntity pOtherEntity) {
		getSource().setPosition(pOtherEntity);
	}

	@Override
	public void setPosition(float pX, float pY) {
		getSource().setPosition(pX, pY);
	}

	@Override
	public boolean isRotated() {
		return getSource().isRotated();
	}

	@Override
	public float getRotation() {
		return getSource().getRotation();
	}

	@Override
	public void setRotation(float pRotation) {
		getSource().setRotation(pRotation);
	}

	@Override
	public float getRotationCenterX() {
		return getSource().getRotationCenterX();
	}

	@Override
	public float getRotationCenterY() {
		return getSource().getRotationCenterY();
	}

	@Override
	public void setRotationCenterX(float pRotationCenterX) {
		getSource().setRotationCenterX(pRotationCenterX);
	}

	@Override
	public void setRotationCenterY(float pRotationCenterY) {
		getSource().setRotationCenterY(pRotationCenterY);
	}

	@Override
	public void setRotationCenter(float pRotationCenterX, float pRotationCenterY) {
		getSource().setRotationCenter(pRotationCenterX, pRotationCenterY);
	}

	@Override
	public boolean isScaled() {
		return getSource().isScaled();
	}

	@Override
	public float getScaleX() {
		return getSource().getScaleX();
	}

	@Override
	public float getScaleY() {
		return getSource().getScaleY();
	}

	@Override
	public void setScaleX(float pScaleX) {
		getSource().setScaleX(pScaleX);
	}

	@Override
	public void setScaleY(float pScaleY) {
		getSource().setScaleY(pScaleY);
	}

	@Override
	public void setScale(float pScale) {
		getSource().setScale(pScale);
	}

	@Override
	public void setScale(float pScaleX, float pScaleY) {
		getSource().setScale(pScaleX, pScaleY);
	}

	@Override
	public float getScaleCenterX() {
		return getSource().getScaleCenterX();
	}

	@Override
	public float getScaleCenterY() {
		return getSource().getScaleCenterY();
	}

	@Override
	public void setScaleCenterX(float pScaleCenterX) {
		getSource().setScaleCenterX(pScaleCenterX);
	}

	@Override
	public void setScaleCenterY(float pScaleCenterY) {
		getSource().setScaleCenterY(pScaleCenterY);
	}

	@Override
	public void setScaleCenter(float pScaleCenterX, float pScaleCenterY) {
		getSource().setScaleCenter(pScaleCenterX, pScaleCenterY);
	}

	@Override
	public float getRed() {
		return getSource().getRed();
	}

	@Override
	public float getGreen() {
		return getSource().getGreen();
	}

	@Override
	public float getBlue() {
		return getSource().getBlue();
	}

	@Override
	public float getAlpha() {
		return getSource().getAlpha();
	}

	@Override
	public void setAlpha(float pAlpha) {
		getSource().setAlpha(pAlpha);
	}

	@Override
	public void setColor(float pRed, float pGreen, float pBlue) {
		getSource().setColor(pRed, pGreen, pBlue);
	}

	@Override
	public void setColor(float pRed, float pGreen, float pBlue, float pAlpha) {
		getSource().setColor(pRed, pGreen, pBlue, pAlpha);
	}

	@Override
	public float[] getSceneCenterCoordinates() {
		return getSource().getSceneCenterCoordinates();
	}

	@Override
	public float[] convertLocalToSceneCoordinates(float pX, float pY) {
		return getSource().convertLocalToSceneCoordinates(pX, pY);
	}

	@Override
	public float[] convertLocalToSceneCoordinates(float pX, float pY,
			float[] pReuse) {
		return getSource().convertLocalToSceneCoordinates(pX, pY, pReuse);
	}

	@Override
	public float[] convertLocalToSceneCoordinates(float[] pCoordinates) {
		return getSource().convertLocalToSceneCoordinates(pCoordinates);
	}

	@Override
	public float[] convertLocalToSceneCoordinates(float[] pCoordinates,
			float[] pReuse) {
		return getSource().convertLocalToSceneCoordinates(pCoordinates, pReuse);
	}

	@Override
	public float[] convertSceneToLocalCoordinates(float pX, float pY) {
		return getSource().convertSceneToLocalCoordinates(pX, pY);
	}

	@Override
	public float[] convertSceneToLocalCoordinates(float pX, float pY,
			float[] pReuse) {
		return getSource().convertSceneToLocalCoordinates(pX, pY, pReuse);
	}

	@Override
	public float[] convertSceneToLocalCoordinates(float[] pCoordinates) {
		return getSource().convertSceneToLocalCoordinates(pCoordinates);
	}

	@Override
	public float[] convertSceneToLocalCoordinates(float[] pCoordinates,
			float[] pReuse) {
		return getSource().convertSceneToLocalCoordinates(pCoordinates, pReuse);
	}

	@Override
	public Transformation getLocalToSceneTransformation() {
		return getSource().getLocalToSceneTransformation();
	}

	@Override
	public Transformation getSceneToLocalTransformation() {
		return getSource().getSceneToLocalTransformation();
	}

	@Override
	public int getChildCount() {
		return getSource().getChildCount();
	}

	@Override
	public void onAttached() {
		getSource().onAttached();
	}

	@Override
	public void onDetached() {
		getSource().onDetached();
	}

	@Override
	public void attachChild(IEntity pEntity) {
		getSource().attachChild(pEntity);
	}

	@Override
	public boolean attachChild(IEntity pEntity, int pIndex) {
		return getSource().attachChild(pEntity, pIndex);
	}

	@Override
	public IEntity getChild(int pIndex) {
		return getSource().getChild(pIndex);
	}

	@Override
	public IEntity getFirstChild() {
		return getSource().getFirstChild();
	}

	@Override
	public IEntity getLastChild() {
		return getSource().getLastChild();
	}

	@Override
	public int getChildIndex(IEntity pEntity) {
		return getSource().getChildIndex(pEntity);
	}

	@Override
	public boolean setChildIndex(IEntity pEntity, int pIndex) {
		return getSource().setChildIndex(pEntity, pIndex);
	}

	@Override
	public IEntity findChild(IEntityMatcher pEntityMatcher) {
		return getSource().findChild(pEntityMatcher);
	}

	@Override
	public boolean swapChildren(int pIndexA, int pIndexB) {
		return getSource().swapChildren(pIndexA, pIndexB);
	}

	@Override
	public boolean swapChildren(IEntity pEntityA, IEntity pEntityB) {
		return getSource().swapChildren(pEntityA, pEntityB);
	}

	@Override
	public void sortChildren() {
		getSource().sortChildren();
	}

	@Override
	public void sortChildren(Comparator<IEntity> pEntityComparator) {
		getSource().sortChildren(pEntityComparator);
	}

	@Override
	public boolean detachSelf() {
		return getSource().detachSelf();
	}

	@Override
	public boolean detachChild(IEntity pEntity) {
		return getSource().detachChild(pEntity);
	}

	@Override
	public IEntity detachChild(IEntityMatcher pEntityMatcher) {
		return getSource().detachChild(pEntityMatcher);
	}

	@Override
	public boolean detachChildren(IEntityMatcher pEntityMatcher) {
		return getSource().detachChildren(pEntityMatcher);
	}

	@Override
	public void detachChildren() {
		getSource().detachChildren();
	}

	@Override
	public void callOnChildren(IEntityCallable pEntityCallable) {
		getSource().callOnChildren(pEntityCallable);
	}

	@Override
	public void callOnChildren(IEntityMatcher pEntityMatcher,
			IEntityCallable pEntityCallable) {
		getSource().callOnChildren(pEntityMatcher, pEntityCallable);
	}

	@Override
	public void registerUpdateHandler(IUpdateHandler pUpdateHandler) {
		getSource().registerUpdateHandler(pUpdateHandler);
	}

	@Override
	public boolean unregisterUpdateHandler(IUpdateHandler pUpdateHandler) {
		return getSource().unregisterUpdateHandler(pUpdateHandler);
	}

	@Override
	public boolean unregisterUpdateHandlers(
			IUpdateHandlerMatcher pUpdateHandlerMatcher) {
		return getSource().unregisterUpdateHandlers(pUpdateHandlerMatcher);
	}

	@Override
	public void clearUpdateHandlers() {
		getSource().clearUpdateHandlers();
	}

	@Override
	public void registerEntityModifier(IEntityModifier pEntityModifier) {
		getSource().registerEntityModifier(pEntityModifier);
	}

	@Override
	public boolean unregisterEntityModifier(IEntityModifier pEntityModifier) {
		return getSource().unregisterEntityModifier(pEntityModifier);
	}

	@Override
	public boolean unregisterEntityModifiers(
			IEntityModifierMatcher pEntityModifierMatcher) {
		return getSource().unregisterEntityModifiers(pEntityModifierMatcher);
	}

	@Override
	public void clearEntityModifiers() {
		getSource().clearEntityModifiers();
	}

	@Override
	public void setUserData(Object pUserData) {
		getSource().setUserData(pUserData);
	}

	@Override
	public Object getUserData() {
		return getSource().getUserData();
	}

	@Override
	public void onDraw(GL10 pGL, Camera pCamera) {
		getSource().onDraw(pGL, pCamera);
	}

	@Override
	public void onUpdate(float pSecondsElapsed) {
		getSource().onUpdate(pSecondsElapsed);
	}

	@Override
	public void reset() {
		getSource().reset();
	}

	@Override
	public boolean contains(float pX, float pY) {
		return getSource().contains(pX, pY);
	}

	@Override
	public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
			float pTouchAreaLocalX, float pTouchAreaLocalY) {
		return getSource().onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX,
				pTouchAreaLocalY);
	}

	@Override
	public boolean isCullingEnabled() {
		return getSource().isCullingEnabled();
	}

	@Override
	public void setCullingEnabled(boolean pCullingEnabled) {
		getSource().setCullingEnabled(pCullingEnabled);
	}

	@Override
	public float getWidth() {
		return getSource().getWidth();
	}

	@Override
	public float getHeight() {
		return getSource().getHeight();
	}

	@Override
	public float getBaseWidth() {
		return getSource().getBaseWidth();
	}

	@Override
	public float getBaseHeight() {
		return getSource().getBaseHeight();
	}

	@Override
	public float getWidthScaled() {
		return getSource().getWidthScaled();
	}

	@Override
	public float getHeightScaled() {
		return getSource().getHeightScaled();
	}

	@Override
	public boolean collidesWith(IShape pOtherShape) {
		return getSource().collidesWith(pOtherShape);
	}

	@Override
	public void setBlendFunction(int pSourceBlendFunction,
			int pDestinationBlendFunction) {
		getSource().setBlendFunction(pSourceBlendFunction,
				pDestinationBlendFunction);
	}

	// /**
	// * 获取XOffset。 功能注释：X坐标偏移量
	// *
	// * @return 当前的float类型的值
	// */
	// public float getXOffset() {
	// return getPositionOffset().getX();
	// }
	//
	// /**
	// * 设置XOffset。 功能注释：X坐标偏移量
	// *
	// * @param value
	// * 要设置的float类型值
	// */
	// public void setXOffset(float value) {
	// getPositionOffset().setX(value);
	// }
	//
	// /**
	// * 设置XOffset为其默认值(0)。 功能注释：X坐标偏移量
	// */
	// public void setXOffsetToDefault() {
	// setXOffset(0);
	// }
	//
	// /**
	// * 获取YOffset。 功能注释：Y坐标偏移量
	// *
	// * @return 当前的float类型的值
	// */
	// public float getYOffset() {
	// return getPositionOffset().getY();
	// }
	//
	// /**
	// * 设置YOffset。 功能注释：Y坐标偏移量
	// *
	// * @param value
	// * 要设置的float类型值
	// */
	// public void setYOffset(float value) {
	// getPositionOffset().setY(value);
	// }
	//
	// /**
	// * 设置YOffset为其默认值(0)。 功能注释：Y坐标偏移量
	// */
	// public void setYOffsetToDefault() {
	// setYOffset(0);
	// }
	//
	// /**
	// * 初始值为null。 功能注释：坐标位置偏移量
	// */
	// private Vector2DF _PositionOffset = null;
	//
	// /**
	// * 获取PositionOffset。 功能注释：坐标位置偏移量
	// *
	// * @return 当前的Vector2DF类型的值
	// */
	// public Vector2DF getPositionOffset() {
	// return _PositionOffset;
	// }
	//
	// /**
	// * 设置PositionOffset。 功能注释：坐标位置偏移量
	// *
	// * @param value
	// * 要设置的Vector2DF类型值
	// */
	// public void setPositionOffset(Vector2DF value) {
	// _PositionOffset = value;
	// }
	//
	// /**
	// * 设置PositionOffset为其默认值(null)。 功能注释：坐标位置偏移量
	// */
	// public void setPositionOffsetToDefault() {
	// setPositionOffset(null);
	// }
	//
	// /**
	// * 设置形状位置偏移量，使之对齐到指定方位
	// * @param direction 方位枚举，可以组合使用
	// */
	// public void setPositionOffsetToAlignment(Direction direction)
	// {
	// setPositionOffsetToAlignment(this, direction);
	// }
	//
	// /**
	// * 设置形状位置偏移量，使之对齐到指定方位
	// * @param shape 形状
	// * @param direction 方位枚举，可以组合使用
	// */
	// public static void setPositionOffsetToAlignment(GameShape shape,
	// Direction direction) {
	// float xp = calculateXposAlignment(direction, shape.getWidth());
	// float yp = calculateYposAlignment(direction, shape.getHeight());
	// shape.getPositionOffset().reset(0-xp, 0-yp);
	// }

	/**
	 * 使形状中心点对齐指定的坐标位置
	 * 
	 * @param x
	 *            x坐标
	 * @param y
	 *            y坐标
	 */
	public void setPositionCenter(float x, float y) {
		setPositionCenter(this, x, y);
	}

	/**
	 * 使形状中心点对齐指定的坐标位置
	 * 
	 * @param shape
	 *            形状
	 * @param x
	 *            x坐标
	 * @param y
	 *            y坐标
	 */
	public static void setPositionCenter(IShape shape, float x, float y) {
		setPosition(shape, x, y, Direction.Center);
	}

	/**
	 * 使形状指定方位对齐指定的坐标位置
	 * 
	 * @param x
	 *            x坐标
	 * @param y
	 *            y坐标
	 * @param direction
	 *            方位枚举，可以组合使用
	 */
	public void setPosition(float x, float y, Direction direction) {
		setPosition(this, x, y, direction);
	}

	/**
	 * 使形状指定方位对齐指定的坐标位置
	 * 
	 * @param shape
	 *            形状
	 * @param x
	 *            x坐标
	 * @param y
	 *            y坐标
	 * @param direction
	 *            方位枚举，可以组合使用
	 */
	public static void setPosition(IShape shape, float x, float y,
			Direction direction) {
		float xp = calculateXposAlignment(direction, shape.getWidth());
		float yp = calculateYposAlignment(direction, shape.getHeight());
		// if (direction.IsContain(Direction.Left)) {
		// xp = direction.IsContain(Direction.Right) ? shape.getWidth() / 2
		// : 0;
		// } else if (direction.IsContain(Direction.Right))
		// xp = shape.getWidth();
		// else
		// xp = shape.getWidth() / 2;
		// if (direction.IsContain(Direction.Top)) {
		// yp = direction.IsContain(Direction.Bottom) ? shape.getHeight() / 2
		// : 0;
		// } else if (direction.IsContain(Direction.Bottom))
		// yp = shape.getHeight();
		// else
		// yp = shape.getHeight() / 2;
		shape.setPosition(x - xp, y - yp);
	}
	
	/**
	 * 获取形状指定方位所对应的坐标位置向量
	 * @param shape 形状
	 * @param direction 方位枚举，可以组合使用
	 * @return 形状指定方位所对应的坐标位置向量
	 */
	public static Vector2DF getPosition(IShape shape, Direction direction){
		float xp = calculateXposAlignment(direction, shape.getWidth());
		float yp = calculateYposAlignment(direction, shape.getHeight());
		return new Vector2DF(shape.getX()+xp, shape.getY()+yp);
	}

	/**
	 * 计算X坐标对齐位置
	 * 
	 * @param direction
	 *            方位枚举，可以组合使用
	 * @param shapeWidth
	 *            形状宽度
	 * @return 对齐位置
	 */
	private static float calculateXposAlignment(Direction direction,
			float shapeWidth) {
		if (direction.IsContain(Direction.Left)) {
			return direction.IsContain(Direction.Right) ? shapeWidth / 2 : 0;
		} else if (direction.IsContain(Direction.Right))
			return shapeWidth;

		return shapeWidth / 2;
	}

	/**
	 * 计算Y坐标对齐位置
	 * 
	 * @param direction
	 *            方位枚举，可以组合使用
	 * @param shapeHeight
	 *            形状高度
	 * @return 对齐位置
	 */
	private static float calculateYposAlignment(Direction direction,
			float shapeHeight) {
		if (direction.IsContain(Direction.Top)) {
			return direction.IsContain(Direction.Bottom) ? shapeHeight / 2 : 0;
		} else if (direction.IsContain(Direction.Bottom))
			return shapeHeight;

		return shapeHeight / 2;
	}
	
	/**
	 * 获取坐标位置向量
	 * @return 二维坐标向量
	 */
	public Vector2DF getPosition(){
		return new Vector2DF(getX(), getY());
	}
	
	/**
	 * 获取形状中心所对应的坐标位置向量
	 * @param direction 方位枚举，可以组合使用
	 * @return 形状中心所对应的坐标位置向量
	 */
	public Vector2DF getPositionCenter(){
		return getPosition(this, Direction.Center);
	}
	
	/**
	 * 获取形状指定方位所对应的坐标位置向量
	 * @param direction 方位枚举，可以组合使用
	 * @return 形状指定方位所对应的坐标位置向量
	 */
	public Vector2DF getPosition(Direction direction){
		return getPosition(this, direction);
	}
	
	/**
	 * 设置坐标位置向量
	 * @param v 二维坐标向量
	 */
	public void setPosition(Vector2DF v){
		setPosition(v.getX(), v.getY());
	}
	
	/**
	 * 使形状中心点对齐指定的坐标位置向量
	 * @param v 二维坐标向量
	 */
	public void setPositionCenter(Vector2DF v){
		setPositionCenter(v.getX(), v.getY());
	}
	
	/**
	 * 设置坐标位置向量
	 * @param v 二维坐标向量
	 * @param direction 方位枚举，可以组合使用
	 */
	public void setPosition(Vector2DF v,Direction direction){
		setPosition(v.getX(), v.getY(),direction);
	}
}
